//
//  @ Project : tp1-algo3
//  @ File Name : Calculador.java
//  @ Date : 04/05/2008
//  @ Author : Claudia, Jorge, Luciana, Luciano
//
package modelo.escenario;

import java.util.LinkedList;
import java.util.Random;
//import escenario.Carrera;
import modelo.auto.*;
import modelo.excepciones.*;
import modelo.jugador.*;

/*CLASE UTILITARIA Calculador*/
public final class Calculador {
	
	/*CONSTANTES*/
	//private static int MAX_SUPERFICIES = 3;  /*Defino la cantidad maxima de superficies posibles*/
	private static int MAX_CLIMAS = 2;		  /*Defino la cantidad maxima de climas posibles*/
	
	/*METODOS*/
	/**Calcula el gandador de la carrera segun el menor tiempo (USANDO MRUV) */
	public static int calcularGanador(LinkedList<Jugador> listaPlayers, Pista pista, int clima) throws NoSuchPlayersException, GameMatchException{
		/* PRECONDICIONES PARA EL MRUV... 
		 * V inicial = 0
		 * t inicial = 0
		 * d inicial = 0
		 * d final   = pista.getLongitud;
		 * a inicial = CTE
		 * */
		
		int i=0;
		int jugador = -1; 			//Ningun jugador en particular
		int totalPlayers = listaPlayers.size();
		double rozamiento = 0;
		double maxDistancia = 0;  	//
		float tiempo = 10;  		//Tiempo para hacer el calculo
		double distancia = 0;
		double aceleracion = 0;
		boolean empate = false;		//Si hay empate no se informa nada mas
		
		/*		Formulatas (MRUV):
		 *1)	t = V/a        
		 *2)  	t = 2*dist/V
		 *3)  	dist = (a/2)*t^2    <------  Yo uso esta
		 *4)  	V = root(dist*2*a)      */
		
		if (listaPlayers.isEmpty()){ /*Si no hay jugadores en la lista*/
			throw new NoSuchPlayersException();
		}
		else{
			while (i < totalPlayers){

				Jugador player = listaPlayers.get(i);
				Auto auto = player.getAuto();
				
				/*Comunicacion entre el auto y la superficie de pista y el clima*/
				rozamiento = calcularRozamiento(clima, pista.getSuperficie());
				auto.setRozamiento(rozamiento);
				
				/*Acelero solo una vez ya que la aceleracion debe ser constante para el MRUV*/
				auto.acelerar();  
				
				/*Actualizo los valores de velocidad y aceleracion*/
				auto.update(tiempo); /*Indico el tiempo transcurrido*/
				aceleracion = auto.getAceleracion();
				
				distancia = (aceleracion/2)*(tiempo*tiempo);  //Formula n (3)
				
				if (distancia == maxDistancia){  
					empate = true;
				}
				else if (distancia > maxDistancia){  
					maxDistancia = distancia;   
					jugador = i;              /*Guardo el jugador con mayor distancia recorrida*/
					empate = false;
				}
				i++;
			}	
		}
		if (empate) throw new GameMatchException();
		return jugador;
	}
	
	/**Se asigna el rozamiento para cada uno de las distintas combinaciones
	 * entre clima y superficie de pista.*/
	public static double calcularRozamiento(int clima, Superficie sup) {
		return sup.calcularRozamiento(clima);
	}
	
	/**Creo Computer Players y los agrego en la lista de Jugadores de la Carrera
	 * Si la lista ya tenia elementos los borro y remplazo por los nuevos*/
	public static void generarComputerPlayers(int cantidad ,LinkedList<modelo.jugador.Jugador> listaPlayers) {
		int i=0;
		while (i < cantidad){
			Auto autoComp = new Auto();
			JugadorComputadora compPlayer = new JugadorComputadora();
			compPlayer.setAuto(autoComp);
			listaPlayers.add(compPlayer);
			i++;
		}	
	}
	
	/**Gnera enteros aleatorios entre 0 y max (exclusive)*/
	private static int enteroAleatorio (int max){
		Random azar = new Random();
		int numero = azar.nextInt(max);
		return numero;
	}
	
	public static Pista elegirPista(LinkedList<Pista> pistas) {
		int aleatorio = enteroAleatorio(pistas.size());
		return pistas.get(aleatorio);
	}
	
	public static int elegirClima() {
		return enteroAleatorio(MAX_CLIMAS);
	}
}
